/**
 * Generate code from /{{projectName}}-core/src/main/java/{{packageName}}/core/{{modules}}/service/impl/Abstract{{entities@SQL}}Service.java.hbs
 */
package cn.ibizlab.core.authorization.service.impl;

import java.util.*;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.util.*;
import cn.ibizlab.util.errors.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Lazy;
import cn.ibizlab.core.authorization.domain.SysRoleMember;
import cn.ibizlab.core.authorization.filter.SysRoleMemberSearchContext;
import cn.ibizlab.core.authorization.service.SysRoleMemberService;
import cn.ibizlab.core.authorization.mapper.SysRoleMemberMapper;
import cn.ibizlab.util.enums.Entities;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.ibizlab.core.ad.domain.SysCommonName;
import cn.ibizlab.core.ad.service.SysCommonNameService;
import cn.ibizlab.core.authorization.domain.SysRole;
import cn.ibizlab.core.authorization.service.SysRoleService;

/**
 * 实体[系统角色成员] 服务对象接口实现
 *
 * @author generator
 */
@Slf4j
public abstract class AbstractSysRoleMemberService extends ServiceImpl<SysRoleMemberMapper,SysRoleMember> implements SysRoleMemberService {

    @Autowired
    @Lazy
    protected SysCommonNameService sysCommonNameService;

    @Autowired
    @Lazy
    protected SysRoleService sysRoleService;

    protected int batchSize = 500;

    public SysRoleMember get(SysRoleMember et) {
        SysRoleMember rt = this.baseMapper.selectEntity(et);
        if(rt == null)
            throw new NotFoundException("数据不存在",Entities.SYS_ROLE_MEMBER.toString(),et.getId());
        rt.copyTo(et,true);
        return et;
    }

    public List<SysRoleMember> getByEntities(List<SysRoleMember> entities) {
        entities.forEach(et->{
            if(ObjectUtils.isEmpty(et.getId()))
                et.setId((String)et.getDefaultKey(true));
            });
        return this.baseMapper.selectEntities(entities);
    }

    public void fillParentData(SysRoleMember et) {
        if(Entities.SYS_COMMON_NAME.equals(et.getContextParentEntity()) && et.getContextParentKey()!=null) {
            et.setMemberUid((String)et.getContextParentKey());
        }
        if(!ObjectUtils.isEmpty(et.getMemberUid())) {
            SysCommonName sysCommonName = et.getCommonName();
            if(sysCommonName == null) {
                sysCommonName = sysCommonNameService.getById(et.getMemberUid());
                et.setCommonName(sysCommonName);
            }
            if(!ObjectUtils.isEmpty(sysCommonName)) {
                et.setMemberType(sysCommonName.getObjectClass());
                et.setMemberUid(sysCommonName.getId());
                et.setMemberName(sysCommonName.getCn());
                et.setMemberDn(sysCommonName.getDn());
                et.setMemberGroupId(sysCommonName.getOrganizationalRoleId());
                et.setDepartmentId(sysCommonName.getDepartmentId());
                et.setOrganizationId(sysCommonName.getOrganizationId());
            }
        }
        if(Entities.SYS_ROLE.equals(et.getContextParentEntity()) && et.getContextParentKey()!=null) {
            et.setRoleId((String)et.getContextParentKey());
            SysRole sysRole = et.getRole();
            if(sysRole == null) {
                sysRole = sysRoleService.getById(et.getRoleId());
                et.setRole(sysRole);
            }
            if(!ObjectUtils.isEmpty(sysRole)) {
                et.setRoleId(sysRole.getId());
                et.setRoleName(sysRole.getName());
                et.setRoleAuthority(sysRole.getAuthority());
                et.setDeploySystemId(sysRole.getDeploySystemId());
            }
        }
    }

    public SysRoleMember getDraft(SysRoleMember et) {
        fillParentData(et);
        return et;
    }

    public Integer checkKey(SysRoleMember et) {
        fillParentData(et);
        if(ObjectUtils.isEmpty(et.getId()))
            et.setId((String)et.getDefaultKey(true));
        return (!ObjectUtils.isEmpty(et.getId()) && this.count(Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getId, et.getId()))>0)?1:0;
    }

    @Override
    @Transactional
    public boolean create(SysRoleMember et) {
        fillParentData(et);
        if(ObjectUtils.isEmpty(et.getId()))
            et.setId((String)et.getDefaultKey(true));
        if(this.baseMapper.insert(et) < 1)
            return false;
        get(et);
        return true;
    }

    @Transactional
    public boolean createBatch(List<SysRoleMember> list) {
        list.forEach(this::fillParentData);
        list.forEach(et->{
            if(ObjectUtils.isEmpty(et.getId()))
                et.setId((String)et.getDefaultKey(true));
            });
        this.saveBatch(list, batchSize);
        return true;
    }

    @Transactional
    public boolean update(SysRoleMember et) {
        fillParentData(et);
        UpdateWrapper<SysRoleMember> qw = et.getUpdateWrapper(true);
        qw.eq("id", et.getId());
        if(!update(et, qw))
            return false;
        get(et);
        return true;
    }

    @Transactional
    public boolean updateBatch(List<SysRoleMember> list) {
        list.forEach(this::fillParentData);
        updateBatchById(list, batchSize);
        return true;
    }

    @Override
    @Transactional
    public boolean save(SysRoleMember et) {
        if(checkKey(et) > 0)
            return getSelf().update(et);
        else
            return getSelf().create(et);
    }

    @Transactional
    public boolean saveBatch(List<SysRoleMember> list) {
        if(ObjectUtils.isEmpty(list))
            return true;
        Map<String,SysRoleMember> before = getByEntities(list).stream().collect(Collectors.toMap(SysRoleMember::getId,e->e));
        List<SysRoleMember> create = new ArrayList<>();
        List<SysRoleMember> update = new ArrayList<>();
        list.forEach(sub->{
            if(ObjectUtils.isEmpty(sub.getId()))
                before.values().stream()
                        .filter(e->ObjectUtils.nullSafeEquals(sub.getDefaultKey(true),e.getDefaultKey(true)))
                        .findFirst().ifPresent(e->sub.setId(e.getId()));
            if(!ObjectUtils.isEmpty(sub.getId()) && before.containsKey(sub.getId()))
                update.add(sub);
            else
                create.add(sub);
        });
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else
            return true;
    }

    @Transactional
    public boolean remove(SysRoleMember et) {
        if(!remove(Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getId, et.getId())))
            return false;
        return true;
    }

    @Transactional
    public boolean removeByEntities(List<SysRoleMember> entities) {
        this.baseMapper.deleteEntities(entities);
        return true;
    }

    public Page<SysRoleMember> searchDefault(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchDefault(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listDefault(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listDefault(context,context.getSelectCond());
        return list;
    }

    public Page<SysRoleMember> searchNav(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchNav(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listNav(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listNav(context,context.getSelectCond());
        return list;
    }

    public Page<SysRoleMember> searchRoleByGroupId(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchRoleByGroupId(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listRoleByGroupId(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listRoleByGroupId(context,context.getSelectCond());
        return list;
    }

    public Page<SysRoleMember> searchRoleByPersonId(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchRoleByPersonId(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listRoleByPersonId(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listRoleByPersonId(context,context.getSelectCond());
        return list;
    }

    public Page<SysRoleMember> searchRolesByUserId(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchRolesByUserId(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listRolesByUserId(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listRolesByUserId(context,context.getSelectCond());
        return list;
    }

    public Page<SysRoleMember> searchUsersByRoleId(SysRoleMemberSearchContext context) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRoleMember> pages=baseMapper.searchUsersByRoleId(context.getPages(),context,context.getSelectCond());
        List<SysRoleMember> list = pages.getRecords();
        return new PageImpl<>(list, context.getPageable(), pages.getTotal());
    }

    public List<SysRoleMember> listUsersByRoleId(SysRoleMemberSearchContext context) {
        List<SysRoleMember> list = baseMapper.listUsersByRoleId(context,context.getSelectCond());
        return list;
    }

    public List<SysRoleMember> findByMemberUid(List<String> memberUids) {
        List<SysRoleMember> list = baseMapper.findByMemberUid(memberUids);
        return list;
    }

    public List<SysRoleMember> findByRoleId(List<String> roleIds) {
        List<SysRoleMember> list = baseMapper.findByRoleId(roleIds);
        return list;
    }

    public boolean removeByMemberUid(String memberUid) {
        return this.remove(Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getMemberUid,memberUid));
    }

    public boolean resetByMemberUid(String memberUid) {
        return this.update(Wrappers.<SysRoleMember>lambdaUpdate().eq(SysRoleMember::getMemberUid,memberUid));
    }

    public boolean saveByCommonName(SysCommonName sysCommonName,List<SysRoleMember> list) {
        if(list==null)
            return true;
        Map<String,SysRoleMember> before = findByMemberUid(sysCommonName.getId()).stream().collect(Collectors.toMap(SysRoleMember::getId,e->e));
        List<SysRoleMember> update = new ArrayList<>();
        List<SysRoleMember> create = new ArrayList<>();

        for(SysRoleMember sub:list) {
            sub.setMemberUid(sysCommonName.getId());
            sub.setCommonName(sysCommonName);
            if(ObjectUtils.isEmpty(sub.getId()))
                before.values().stream()
                        .filter(e->ObjectUtils.nullSafeEquals(sub.getDefaultKey(true),e.getDefaultKey(true)))
                        .findFirst().ifPresent(e->sub.setId(e.getId()));
            if(!ObjectUtils.isEmpty(sub.getId())&&before.containsKey(sub.getId())) {
                before.remove(sub.getId());
                update.add(sub);
            }
            else
                create.add(sub);
        }
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else if(!before.isEmpty() && !getSelf().removeBatch(before.keySet()))
            return false;
        else
            return true;
    }

    public boolean removeByRoleId(String roleId) {
        return this.remove(Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getRoleId,roleId));
    }

    public boolean resetByRoleId(String roleId) {
        return this.update(Wrappers.<SysRoleMember>lambdaUpdate().eq(SysRoleMember::getRoleId,roleId));
    }

    public boolean saveByRole(SysRole sysRole,List<SysRoleMember> list) {
        if(list==null)
            return true;
        Map<String,SysRoleMember> before = findByRoleId(sysRole.getId()).stream().collect(Collectors.toMap(SysRoleMember::getId,e->e));
        List<SysRoleMember> update = new ArrayList<>();
        List<SysRoleMember> create = new ArrayList<>();

        for(SysRoleMember sub:list) {
            sub.setRoleId(sysRole.getId());
            sub.setRole(sysRole);
            if(ObjectUtils.isEmpty(sub.getId()))
                before.values().stream()
                        .filter(e->ObjectUtils.nullSafeEquals(sub.getDefaultKey(true),e.getDefaultKey(true)))
                        .findFirst().ifPresent(e->sub.setId(e.getId()));
            if(!ObjectUtils.isEmpty(sub.getId())&&before.containsKey(sub.getId())) {
                before.remove(sub.getId());
                update.add(sub);
            }
            else
                create.add(sub);
        }
        if(!update.isEmpty())
            update.forEach(item->this.getSelf().update(item));
        if(!create.isEmpty() && !getSelf().createBatch(create))
            return false;
        else if(!before.isEmpty() && !getSelf().removeBatch(before.keySet()))
            return false;
        else
            return true;
    }

    @Override
    public List<JSONObject> select(String sql, Map param){
        return this.baseMapper.selectBySQL(sql,param);
    }

    @Override
    @Transactional
    public boolean execute(String sql , Map param){
        if (sql == null || sql.isEmpty()) {
            return false;
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.INSERT_ONE.getMethod())) {
            return this.baseMapper.insertBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.UPDATE.getMethod())) {
            return this.baseMapper.updateBySQL(sql,param);
        }
        if (sql.toLowerCase().trim().startsWith(SqlMethod.DELETE.getMethod())) {
            return this.baseMapper.deleteBySQL(sql,param);
        }
        log.warn("暂未支持的SQL语法");
        return true;
    }

    @Override
    protected Class currentMapperClass() {
        return SysRoleMemberMapper.class;
    }

    @Override
    protected Class currentModelClass() {
        return SysRoleMember.class;
    }
}